/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package servant;

import common.Envelope;
import common.FileReceiver;
import common.Framer;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;

/**
 *
 * @author Mateusz
 */
public class ReceiverProtocol {

    private static boolean busy = false;
    private boolean ended = false;
    private Framer framer;
    private File initial;
    private File current;
    private Socket socket;
    private boolean started = false;
    private boolean state = true;
    private static final Logger LOGGER = Logger.getLogger(ReceiverProtocol.class.getName());;

    public ReceiverProtocol(Socket socket, Framer framer, File path) {
        this.framer = framer;
        this.initial = this.current = path;
        this.socket = socket;
        LOGGER.log(Level.INFO, "Receiving protocol initiated for address {0}", socket.getInetAddress().getHostAddress());
    }

    public static void setBusy(boolean busy) {
        ReceiverProtocol.busy = busy;
        LOGGER.log(Level.INFO, "Protocol setted busy.");
    }

    public boolean isEnded() {
        return ended;
    }

    public void process(Envelope envelope) {
        int code = envelope.getCode();
        LOGGER.log(Level.INFO, "Processing envelope {0}", envelope);
        switch (code) {
            case 0:
                if (!started) {
                    hello();
                }
                break;
            case 1:
                if (started) {
                    receivingData();
                }
                break;
            case 2:
                if (started) {
                    receiveAnswerRequest();
                }
                break;
            case 3:
                if (started) {
                    goodbye();
                }
                break;
            case 11:
                if (started) {
                    newFolder(envelope.getMessage());
                }
                break;
            case 12:
                if (started) {
                    newFile(envelope.getMessage());
                }
                break;
            case 13:
                if (started) {
                    backFolder();
                }
                break;
            case 14:
                if (started) {
                    receiveTestClassPath(envelope.getMessage());
                }
                break;
            case 15:
                if (started) {
                    end();
                }
                break;
        }
    }

    private void hello() {
        LOGGER.log(Level.INFO, "Received hello");
        if (!busy) {
            LOGGER.log(Level.INFO, "accepted, sending hello");
            framer.sendCode(0);
            setBusy(true);
            Config.getInstance().setTestClassPath(null);
        } else {
            LOGGER.log(Level.INFO, "rejected, sending busy");
            framer.sendCode(30);
            ended = true;
        }
    }

    private void receivingData() {
        try {
            LOGGER.log(Level.INFO, "Receiving data initiated");
            current = initial;
            FileUtils.cleanDirectory(initial);
            LOGGER.log(Level.INFO, "OK - directory cleaned");
            framer.sendCode(19);
        } catch (IOException ex) {
            LOGGER.log(Level.INFO, "Error while cleaning directory, sending code 18");
            state = false;
            framer.sendCode(18);
        }
    }

    private void newFolder(String name) {
        LOGGER.log(Level.INFO, "Received new folder");
        current = new File(current.getPath() + "/name/");
        boolean res = current.mkdir();
        if (!res) {
            state = false;
            framer.sendCode(16);
        } else {
            LOGGER.log(Level.INFO, "OK - New folder created");
            framer.sendCode(19);
        }
    }

    private void newFile(String name) {
        try {
            LOGGER.log(Level.INFO, "Received new file");
            current = new File(current.getPath() + "/name");
            current.createNewFile();
            LOGGER.log(Level.INFO, "OK - new file created, downloading file");
            framer.sendCode(19);
            FileReceiver frec = new FileReceiver();
            frec.start(socket, current);
            LOGGER.log(Level.INFO, "OK - file downloaded");
            framer.sendCode(19);
        } catch (IOException ex) {
            LOGGER.log(Level.INFO, "Error while creating or downloading data");
            state = false;
            framer.sendCode(17);
        }
    }

    private void backFolder() {
        LOGGER.log(Level.INFO, "Received bac folder");
        StringBuilder builder = new StringBuilder(current.getPath());
        int end = builder.length();
        int index = builder.lastIndexOf("/");
        builder.delete(index, end);
        index = builder.lastIndexOf("/");
        builder.delete(index + 1, end);
        current = new File(builder.toString());
    }

    private void receiveTestClassPath(String path) {
        LOGGER.log(Level.INFO, "Received test classpath {0}", path);
        Config.getInstance().setTestClassPath(path);
    }

    private void end() {
        LOGGER.log(Level.INFO, "Received end");
    }

    private void receiveAnswerRequest() {
        LOGGER.log(Level.INFO, "Received answer request");
        framer.sendCode(21);
        //TODO
    }

    private void sendBusy() {
        LOGGER.log(Level.INFO, "Sending busy");
        framer.sendCode(30);
    }

    private void goodbye() {
        LOGGER.log(Level.INFO, "Goodbye");
        ended = true;
        Config.getInstance().setTestReady(state);
    }
}
